#include "token.h"
#include "input.h"
#include "stateMachine.h"
#include "state.h"
#include "lex.h"
#include <stdarg.h>

#include <vector>
#include <string>
using std::vector;
using std::string;

#include "parser.h"
 

int Parser::_JumpIndex = 0;

void Parser::ExitOnCodeError(const char *fmt, ...)
{
	va_list ap;

	va_start(ap, fmt);
	vfprintf(stderr, fmt, ap);
	va_end(ap);

	system("pause");
	exit(1);
}


bool Parser::isFunc(const string &name)
{
	map<string, Function>::iterator Iter = _functions.find(name);
	if (Iter != _functions.end())
		return true;

	return false;
}


bool Parser::addFunc(const string &name)
{
	if(isFunc(name))
		return false;

	_functions[name] = Function(name);
	_currFun = &(_functions[name]);
	return true;
}


bool Parser::parseSourceCode(const char *filename)
{
	//printf("parser begin!\n");

	if (!_lex.loadFile(filename)) {
		printf("Load File Error!\n");
		return false;
	}

	//printf("file %s load Ok!\n");

	Token token;
	while (true) {
		parseStatement();
		token = _lex.getNextToken();
		if (token == TOKEN_END_OF_STREAM)
			break;
		else
			_lex.saveToken(token);
	}

    return true;
	//printf("Parser end!\n");
}



void Parser::parseStatement()
{
	Token token = _lex.getNextToken();

	// token is ';' , just return
	if (token == TOKEN_OP_SEMICOLON)
		return;

	switch(token) {
		case TOKEN_COMMENTLINE:
			break;
		case TOKEN_END_OF_STREAM:
			ExitOnCodeError("%s %s %d:Unexcepted end of file", __FILE__, __FUNCTION__, __LINE__);
			break;
		case TOKEN_OP_LBRACE:
			parseBlock();
			break;
		case TOKEN_K_FUNC:
			parseFunc();
			break;
		case TOKEN_K_VAR:
			parseVar();
			break;
		case TOKEN_INT:
		case TOKEN_FLOAT:
		case TOKEN_STRING:
		case TOKEN_OP_LPARA:
		case TOKEN_AM_ADD:
		case TOKEN_AM_SUB:
		case TOKEN_UO_NOT:
		case TOKEN_K_TRUE:
		case TOKEN_K_FALSE:
			_lex.saveToken(token);
			parseExpr();
			break;

		case TOKEN_IDENT:
			{
				if (_currFun == NULL) 
					ExitOnCodeError("%s %s %d: Statement in global scope!\n", __FILE__, __FUNCTION__, __LINE__);
				
				if(_currFun->isVar(_lex.getCurrLexme())) {
					_lex.saveToken(token);
					parseAssign();
				} else { //isFunc(_lex.getCurrLexme())  may be a host api func 
					string tFuncName = _lex.getCurrLexme();
					Token _token;

					readToken(TOKEN_OP_LPARA);	

					while (true) {
						_token = _lex.getNextToken();
						if (_token != TOKEN_OP_RPARA) {
							_lex.saveToken(_token);
							parseExpr();
							_token = _lex.getNextToken();
							if (_token == TOKEN_OP_RPARA)
							       break;
							if (_token != TOKEN_OP_COMMA)
								ExitOnCodeError("%s %s %d:read param error!\n",  __FILE__, __FUNCTION__, __LINE__);
						} else {
							break;
						}
					}

					_currFun->addInstr("%s  Call %s\n", spaceBuf, tFuncName.c_str()); 
					//_currFun->addInstr("%s  Push _retVal\n", spaceBuf);	
		
					readToken(TOKEN_OP_SEMICOLON);

				} 
				break;
			}

		case TOKEN_K_RETURN:
			parseReturn();
			break;

		case TOKEN_K_WHILE:
			parseWhile();
			break;
		
		case TOKEN_K_BREAK:
			parseBreak();
			break;
		case TOKEN_K_CONTINUE:
			parseContinue();
			break;
		case TOKEN_K_IF:
			parseIf();
			break;
		default:
			ExitOnCodeError("%s %s %d: Unexcepted input", __FILE__, __FUNCTION__, __LINE__);
			break;
	}
}


void Parser::parseIf()
{
	if (_currFun == NULL)
		ExitOnCodeError("%s %s %d: If Statement in global Scope", __FILE__, __FUNCTION__, __LINE__);

	int falseIndex  = nextJumpIndex();

	readToken(TOKEN_OP_LPARA);
	parseExpr();
	readToken(TOKEN_OP_RPARA);

	_currFun->addInstr("%s  Pop _T0\n", spaceBuf);
	_currFun->addInstr("%s  Je  _T0, 0, _L%d\n", spaceBuf, falseIndex);
	parseStatement();

	Token token = _lex.getNextToken();
	if (token == TOKEN_K_ELSE) {
		int skipIndex  = nextJumpIndex();
		_currFun->addInstr("%s  Jmp _L%d\n", spaceBuf, skipIndex);
		_currFun->addInstr("%s_L%d:\n", spaceBuf, falseIndex);
		parseStatement();
		_currFun->addInstr("%s_L%d:\n", spaceBuf, skipIndex);
	} else {
		_currFun->addInstr("%s_L%d:\n", spaceBuf, falseIndex);
		_lex.saveToken(token);
	}
}


void Parser::parseContinue()
{
	if (_currFun == NULL)
		ExitOnCodeError("%s %s %d: Break Statement in global Scope", __FILE__, __FUNCTION__, __LINE__);

	readToken(TOKEN_OP_SEMICOLON);
	int target = _currFun->peek_s_loop();
	if (target < 0)
		ExitOnCodeError("%s %s %d: Peek Loop Target Error!", __FILE__, __FUNCTION__, __LINE__);

	_currFun->addInstr("%s  Jmp _L%d\n", spaceBuf, target);
}


void Parser::parseBreak()
{
	if (_currFun == NULL)
		ExitOnCodeError("%s %s %d: Break Statement in global Scope", __FILE__, __FUNCTION__, __LINE__);

	readToken(TOKEN_OP_SEMICOLON);
	int target = _currFun->peek_e_loop();
	if (target < 0)
		ExitOnCodeError("%s %s %d: Peek Loop Target Error!", __FILE__, __FUNCTION__, __LINE__);

	_currFun->addInstr("%s  Jmp _L%d\n", spaceBuf, target);
}


void Parser::parseWhile()
{
	if (_currFun == NULL)
		ExitOnCodeError("%s %s %d: While Statement in global Scope!\n", __FILE__, __FUNCTION__, __LINE__);

	int startIndex = nextJumpIndex();
	int endIndex  = nextJumpIndex();

	_currFun->addInstr("%s_L%d:\n", spaceBuf, startIndex);
	readToken(TOKEN_OP_LPARA);
	parseExpr();
	readToken(TOKEN_OP_RPARA);
	_currFun->addInstr("%s  Pop _T0\n", spaceBuf);
	_currFun->addInstr("%s  Je  _T0, 0, _L%d\n", spaceBuf, endIndex);

	_currFun->push_loop(startIndex, endIndex);
	parseStatement();
	_currFun->pop_loop();

	_currFun->addInstr("%s  Jmp _L%d\n", spaceBuf, startIndex);
	_currFun->addInstr("%s_L%d:\n", spaceBuf, endIndex);
}



void Parser::parseReturn()
{
	if (_currFun == NULL)
		ExitOnCodeError("%s %s %d: Return in global scope!\n", __FILE__, __FUNCTION__, __LINE__);

	Token token = _lex.getNextToken();
	if (token != TOKEN_OP_SEMICOLON) {
		_lex.saveToken(token);
		parseExpr();
		if (_currFun->getName() == MAIN_NAME)
			_currFun->addInstr("%s  Pop _T0\n", spaceBuf);
		else
			_currFun->addInstr("%s  Pop _RetVal\n", spaceBuf);
	} else {
		_currFun->addInstr("%s  Mov _T0, 0\n", spaceBuf);
	}
/*
	if (_currFun->getName() == MAIN_NAME)
		_currFun->addInstr("%s  Exit\n", spaceBuf);
	else 
		_currFun->addInstr("%s  Ret\n", spaceBuf);
*/
}


void Parser::parseAssign()
{
	bool isArray = false;

	if (_currFun == NULL)
		ExitOnCodeError("%s %s %d: Assignment illegal in global scope!\n", __FILE__, __FUNCTION__, __LINE__);

	Token token = _lex.getNextToken();
	string IdentName = _lex.getCurrLexme();

	token = _lex.getNextToken();
	if (token == TOKEN_OP_LBRACKET) {
		token = _lex.getNextToken();
		if (token == TOKEN_OP_LBRACKET)
			ExitOnCodeError("%s %s %d: Invalid Expression!\n", __FILE__, __FUNCTION__, __LINE__);
		
		_lex.saveToken(token);
		parseExpr();
		readToken(TOKEN_OP_RBRACKET);
		isArray = true;
	} else {
		_lex.saveToken(token);
	}

	token = _lex.getNextToken();
	if (token != TOKEN_AS_MUL && token != TOKEN_AS_ADD &&
	    token != TOKEN_AS_SUB && token != TOKEN_AS_DIV &&
	    token != TOKEN_AS_MOD && token != TOKEN_AS_XOR &&
	    token != TOKEN_AS_AND && token != TOKEN_AS_OR  &&
	    token != TOKEN_AS_LSH && token != TOKEN_AS_RSH &&
	    token != TOKEN_AS_AS)
		ExitOnCodeError("%s %s %d: Invalid assigment operation", __FILE__, __FUNCTION__, __LINE__);

	parseExpr();
	readToken(TOKEN_OP_SEMICOLON);

	_currFun->addInstr("%s  Pop _T0\n", spaceBuf);
	
	if (isArray) {
		_currFun->addInstr("%s  Pop _T1\n", spaceBuf);
	}

	const char *instr_str;

	switch(token) {
		case TOKEN_AS_AS:
			instr_str = "Mov";
			break;
		case TOKEN_AS_MUL:
			instr_str = "Mul";
			break;	       
		case TOKEN_AS_ADD:
			instr_str = "Add";
			break;
		case TOKEN_AS_SUB:
			instr_str = "Sub";
			break;
		case TOKEN_AS_DIV:
			instr_str = "Div";
			break;
		case TOKEN_AS_MOD: 
			instr_str = "Mod";
			break;
		case TOKEN_AS_XOR:
			instr_str = "Xor";
			break;
		case TOKEN_AS_AND:
			instr_str = "And";
			break;
		case TOKEN_AS_OR:
			instr_str = "Or";
			break;
		case TOKEN_AS_LSH:
			instr_str = "Lsh";
			break;
		case TOKEN_AS_RSH:
			instr_str = "Rsh";
			break;
	}

	if (isArray) 
		_currFun->addInstr("%s  %s  %s[_T1], _T0\n", spaceBuf, instr_str, 
				IdentName.c_str());
	else
		_currFun->addInstr("%s  %s  %s, _T0\n", spaceBuf, instr_str, 
				IdentName.c_str());

}


void Parser::parseFunc()
{
	Token token;
	if (_currFun != NULL)
		ExitOnCodeError("%s %s %d: Nested function definition!", __FILE__, __FUNCTION__, __LINE__);

	readToken(TOKEN_IDENT);

	string funcName = _lex.getCurrLexme();
	if (!addFunc(funcName)) {
		ExitOnCodeError("%s %s %d: Function redefinition", __FILE__, __FUNCTION__, __LINE__);
	}

	readToken(TOKEN_OP_LPARA);

	token = _lex.getNextToken();

	if (token != TOKEN_OP_RPARA) {

		_lex.saveToken(token);
		
		while (true) {
			token = _lex.getNextToken();

			_currFun->addParam(_lex.getCurrLexme());

			token = _lex.getNextToken();
			if (token == TOKEN_OP_RPARA)
				break;

			if (token != TOKEN_OP_COMMA)
				ExitOnCodeError("%s %s %d :expect COMMA\n", __FILE__, __FUNCTION__, __LINE__);
		}
	}

	readToken(TOKEN_OP_LBRACE);

	parseBlock();

	_currFun = NULL;

}


void Parser::parseBlock()
{
	Token token;

	if (_currFun == NULL)
		ExitOnCodeError("%s %s %d: Global scope block\n", __FILE__, __FUNCTION__, __LINE__);
	
	spaceBuf[_blockLevel++] = '\t';
	
	token = _lex.getNextToken();
	while (token != TOKEN_OP_RBRACE) {
		_lex.saveToken(token);
		parseStatement();
		token = _lex.getNextToken();
	}
	
	spaceBuf[--_blockLevel] = '\0';
}


void Parser::parseVar()
{
	readToken(TOKEN_IDENT);
	string Ident = _lex.getCurrLexme();
	int size = 1;

	Token token = _lex.getNextToken();
	if (token == TOKEN_OP_LBRACKET) {
		readToken(TOKEN_INT);
		size = atoi(_lex.getCurrLexme());
		readToken(TOKEN_OP_RBRACKET);
	} else {
	    _lex.saveToken(token);
	}    
	
	if (_currFun) {
		_currFun->addSymbol(Ident, size);
	} else {
	    _globalScope.addSymbol(Ident, size);
	}    
	 	
	readToken(TOKEN_OP_SEMICOLON);
}
	

void Parser::readToken(Token token)
{
	Token _token = _lex.getNextToken();
	if (_token != token) {
		printf("expect %s, get %s\n", getTokenName(token), getTokenName(_token));
		ExitOnCodeError("%s %s %d: Unexpect\n", __FILE__, __FUNCTION__, __LINE__);
	}
}


void Parser::parseExpr()
{
	Token _token;
        
	parseSubExpr();

	while (true) {
		Token _token = _lex.getNextToken();
		if (_token != TOKEN_LG_AND && _token != TOKEN_LG_OR &&
		    _token != TOKEN_LG_LESSEQ && _token != TOKEN_LG_CREATEQ &&
		    _token != TOKEN_LG_EQ && _token != TOKEN_LG_LESS &&
		    _token != TOKEN_LG_GREAT && _token != TOKEN_LG_NOT) {
			_lex.saveToken(_token);
			break;
		}

		parseSubExpr();

		int falseIndex = nextJumpIndex();
		int exitIndex = nextJumpIndex();

		_currFun->addInstr("%s  Pop _T1\n", spaceBuf);
		_currFun->addInstr("%s  Pop _T0\n", spaceBuf);
		
		switch(_token) {
			case TOKEN_LG_AND:
				_currFun->addInstr("%s  Je  _T0, 0, _L%d\n", spaceBuf, falseIndex);
				_currFun->addInstr("%s  Je  _T1, 0, _L%d\n", spaceBuf, falseIndex);
				_currFun->addInstr("%s  Push 1\n", spaceBuf);
				_currFun->addInstr("%s  Jmp  _L%d\n", spaceBuf, exitIndex);
				_currFun->addInstr("%s_L%d:\n", spaceBuf, exitIndex);
				break;	
			case TOKEN_LG_OR:	
				_currFun->addInstr("%s  Jne  _T0, 0, _L%d\n", spaceBuf, falseIndex);
				_currFun->addInstr("%s  Jne  _T1, 0, _L%d\n", spaceBuf, falseIndex);
				_currFun->addInstr("%s  Push 0\n", spaceBuf);
				_currFun->addInstr("%s  Jmp  _L%d\n", spaceBuf, exitIndex);
				_currFun->addInstr("%s_L%d:\n", spaceBuf, falseIndex);
				_currFun->addInstr("%s  Push 1\n", spaceBuf);
				_currFun->addInstr("%s_L%d:\n", spaceBuf, exitIndex);
				break;	
			case TOKEN_LG_GREAT:
			case TOKEN_LG_LESS:
			case TOKEN_LG_EQ:
			case TOKEN_LG_NOT:
			case TOKEN_LG_CREATEQ:
			case TOKEN_LG_LESSEQ:
				if (_token == TOKEN_LG_GREAT)
					_currFun->addInstr("%s  Jg  _T0, _T1, _L%d\n", spaceBuf, falseIndex);
				else if (_token == TOKEN_LG_LESS)
					_currFun->addInstr("%s  Jl  _T0, _T1, _L%d\n", spaceBuf, falseIndex);
				else if (_token == TOKEN_LG_EQ)
					_currFun->addInstr("%s  Je  _T0, _T1, _L%d\n", spaceBuf, falseIndex);
				else if (_token == TOKEN_LG_CREATEQ)
					_currFun->addInstr("%s  Jge  _T0, _T1, _L%d\n", spaceBuf, falseIndex);
				else if (_token == TOKEN_LG_NOT)
					_currFun->addInstr("%s  Jne  _T0, _T1, _L%d\n", spaceBuf, falseIndex);
				else
					_currFun->addInstr("%s  Jle  _T0, _T1, _L%d\n", spaceBuf, falseIndex);
				_currFun->addInstr("%s  Push 0\n", spaceBuf);
				_currFun->addInstr("%s  Jmp  _L%d\n", spaceBuf, exitIndex);
				_currFun->addInstr("%s_L%d:\n", spaceBuf, falseIndex);
				_currFun->addInstr("%s  Push 1\n", spaceBuf);
				_currFun->addInstr("%s_L%d:\n", spaceBuf, exitIndex);
				break;
		}
		
	}
}


void Parser::parseSubExpr()
{
	Token _token;
        
	parseTerm();

	while (true) {
		Token _token = _lex.getNextToken();
		if (_token != TOKEN_AM_ADD && _token != TOKEN_AM_SUB) {
			_lex.saveToken(_token);
			break;
		}

		parseTerm();

		_currFun->addInstr("%s  Pop  _T1\n", spaceBuf);
		_currFun->addInstr("%s  Pop  _T0\n", spaceBuf);
		switch(_token) {
			case TOKEN_AM_ADD:
				_currFun->addInstr("%s  Add  _T0, _T1\n", spaceBuf);
				break;
			case TOKEN_AM_SUB:
				_currFun->addInstr("%s  Sub  _T0, _T1\n", spaceBuf);
				break;
		}
		
		_currFun->addInstr("%s  Push _T0\n", spaceBuf);
	}
}


void Parser::parseTerm()
{
	Token _token;

	parseFactor();

	while (true) {
		Token _token = _lex.getNextToken();
		if (_token != TOKEN_AM_MUL && _token != TOKEN_AM_DIV) {
			_lex.saveToken(_token);
			break;
		}

		parseFactor();

		_currFun->addInstr("%s  Pop _T1\n", spaceBuf);
		_currFun->addInstr("%s  Pop _T0\n", spaceBuf);

		switch(_token) {
			case TOKEN_AM_MUL:
				_currFun->addInstr("%s  Mul  _T0, _T1\n", spaceBuf);
				break;
			case TOKEN_AM_DIV:
				_currFun->addInstr("%s  Div  _T0, _T1\n", spaceBuf);
				break;
		}
		
		_currFun->addInstr("%s  Push _T0\n");
	}
}



void Parser::parseFactor()
{
	bool  unary = false;
	Token _saveTk;
	Token _token = _lex.getNextToken();

	if(_token == TOKEN_AM_ADD || _token == TOKEN_AM_SUB || _token == TOKEN_UO_NOT) { 
		unary = true;
		_saveTk = _token;
		_token = _lex.getNextToken();
	}

	switch(_token) {
		case TOKEN_INT:
			_currFun->addInstr("%s  Push %d\n", spaceBuf, atoi(_lex.getCurrLexme()));
			break;
		case TOKEN_FLOAT:
			_currFun->addInstr("%s  Push %f\n", spaceBuf, atof(_lex.getCurrLexme()));
			break;
		case TOKEN_IDENT:
			{
				string ident = _lex.getCurrLexme();
				if (!_currFun->isVar(ident) && !isFunc(ident)) {
					//ExitOnCodeError("%s %s %d: Undefine Ident %s", __FILE__, __FUNCTION__, __LINE__, ident.c_str());
				}

				_token = _lex.getNextToken();
				if (_token == TOKEN_OP_LBRACKET) {
					parseExpr();
					readToken(TOKEN_OP_RBRACKET);
					_currFun->addInstr("%s  Pop  _T0\n", spaceBuf);
					_currFun->addInstr("%s  Push %s[_T0]\n", spaceBuf, ident.c_str());
				} else if (_token == TOKEN_OP_LPARA) { 
					while (true) {
						_token = _lex.getNextToken();
						if (_token != TOKEN_OP_RPARA) {
							_lex.saveToken(_token);
							parseExpr();
							_token = _lex.getNextToken();
							if (_token == TOKEN_OP_RPARA)
							       break;
							if (_token != TOKEN_OP_COMMA)
								ExitOnCodeError("%s %s %d: read param error!\n", __FILE__, __FUNCTION__, __LINE__);
						} else {
							break;
						}
					}
					_currFun->addInstr("%s  Call %s\n", spaceBuf, ident.c_str()); 
					_currFun->addInstr("%s  Push _RetVal\n", spaceBuf);	
				}else {
					_lex.saveToken(_token);
					_currFun->addInstr("%s  Push %s\n", spaceBuf, ident.c_str());
				}
			}
			break;

		case TOKEN_OP_LPARA:
			parseExpr();
			readToken(TOKEN_OP_RPARA);
			break;

		case TOKEN_K_TRUE:
		case TOKEN_K_FALSE:
			_currFun->addInstr("%s  Push %d\n", spaceBuf, _token == TOKEN_K_TRUE ? 1 : 0);
			break;

		case TOKEN_STRING:
			_currFun->addInstr("%s  Push %s\n", spaceBuf, _lex.getCurrLexme());
			break;

		default:
			ExitOnCodeError("%s %s %d: Invalid input", __FILE__, __FUNCTION__, __LINE__);
	}

	
	if (unary) {
		switch(_saveTk) {
			case TOKEN_UO_NOT:
			{
				int trueIndex = nextJumpIndex();
				int exitIndex = nextJumpIndex();
				_currFun->addInstr("%s  Pop  _T0\n", spaceBuf);
				_currFun->addInstr("%s  Je   _T0, 0, _L%d\n", spaceBuf, trueIndex);
				_currFun->addInstr("%s  Push 0\n", spaceBuf);
				_currFun->addInstr("%s  Jmp  _L%d\n", spaceBuf, exitIndex);
				_currFun->addInstr("%s_L%d:\n", spaceBuf, trueIndex);
				_currFun->addInstr("%s  Push 1\n", spaceBuf);
				_currFun->addInstr("%s_L%d:\n", spaceBuf, exitIndex);
				break;
			}		
			case TOKEN_AM_SUB:
				_currFun->addInstr("%s  Pop  _T0\n", spaceBuf);
				_currFun->addInstr("%s  Neg  _T0\n", spaceBuf);
				_currFun->addInstr("%s  Push _T0\n", spaceBuf);
				break;
		}
	}
}


void Parser::codeEmit(const char *file)
{
	FILE *fp = stdout;
	if (file) {
		fp = fopen(file, "w");
		if (fp == NULL)
			fp = stdout;
	}

	// global data start at begining of the line
	
	_globalScope.addSymbol("_T0", 1);
	_globalScope.addSymbol("_T1", 1);
	_globalScope.codeEmit(fp, 0x0d); 
	
	map<string, Function>::iterator Iter = _functions.begin();
	while (Iter != _functions.end()) {
		fprintf(fp, "Func %s\n", Iter->first.c_str());
		fprintf(fp, "{\n");
		Iter->second.codeEmit(fp);
		fprintf(fp, "\n}\n\n\n");
		++Iter;
	}

	if (file)
		fclose(fp);
}

bool Function::isVar(const string &name)
{
	int i;

	for (i = 0; i < _symbolArray.size(); ++i) {
		if (_symbolArray[i]._name == name)
			return true;
	}

	for (i = 0; i < _paramArray.size(); ++i) {
		if (_paramArray[i] == name)
			return true;
	}

	return false;
}



bool Function::addSymbol(const string &symbol, int size)
{
	if (isVar(symbol))
		return false;

	Var var = {symbol, size};
	_symbolArray.push_back(var);
	return true;
}


bool Function::addParam(const string &param)
{
	if (isVar(param))
		return false;

	_paramArray.push_back(param);
	return true;
}


void Function::addInstr(const char *fmt, ...)
{
	char buf[1024*4];
	va_list ap;

	va_start(ap, fmt);
	vsnprintf(buf, sizeof(buf), fmt, ap);
	va_end(ap);

	_instrArray.push_back(buf);
}


void Function::push_loop(int i, int j)
{
	Jump jmp = {i, j};
	_loopStack.push_back(jmp);
}

int Function::peek_s_loop()
{
	if (_loopStack.size() == 0)
		return -1;
			
	return _loopStack.back()._start;
}

int Function::peek_e_loop()
{
	if (_loopStack.size() == 0)
		return -1;
			
	return _loopStack.back()._end;
}


void Function::pop_loop()
{
	_loopStack.pop_back();
}

void Function::codeEmit(FILE *fp, char space)
{
	int i;
	
	for (i = 0; i < _paramArray.size(); ++i)
		fprintf(fp, "%cParam %s\n", space, _paramArray[i].c_str());

	fprintf(fp, "\n\n");
	for (i = 0; i < _symbolArray.size(); ++i) {
		fprintf(fp, "%cVar %s", space, _symbolArray[i]._name.c_str());
		if (_symbolArray[i]._size > 1) 
			fprintf(fp, "[ %d ]", _symbolArray[i]._size);
		fprintf(fp, "\n");
	}

	
	fprintf(fp, "\n\n");
	for (i = 0; i < _instrArray.size(); ++i) {
		fprintf(fp, "%c%s", space, _instrArray[i].c_str());
	}
	
}


int main(int argc, char *argv[])
{
	Parser ps;

    char buf[512];
    
    if (argc < 2)
        exit(2);

	if (!ps.parseSourceCode(argv[1])) {
        fprintf(stderr, "Open source file %s error!", buf);
        exit(1);
    }

    buf[0] = '!';
    buf[1] = 0;
    strcat(buf, argv[1]);

    printf("Compile file %s out to %s\n", argv[1], buf);
	ps.codeEmit(buf);

	return 0;
}
